/* * JBoss, Home of Professional Open Source. * Copyright 2009, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.switchboard.mc.dependency; import javax.naming.Binding; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.event.EventContext; import javax.naming.event.NamespaceChangeListener; import javax.naming.event.NamingEvent; import javax.naming.event.NamingExceptionEvent; import org.jboss.dependency.plugins.AbstractDependencyItem; import org.jboss.dependency.spi.Controller; import org.jboss.dependency.spi.ControllerState; import org.jboss.logging.Logger; import org.jboss.reloaded.naming.CurrentComponent; import org.jboss.reloaded.naming.spi.JavaEEComponent; import org.jboss.switchboard.mc.SwitchBoardImpl; /** * JNDIDependencyItem * * @author Jaikiran Pai * @version $Revision: $ */ public class JNDIDependencyItem extends AbstractDependencyItem implements NamespaceChangeListener { private static Logger logger = Logger.getLogger(JNDIDependencyItem.class); private SwitchBoardImpl switchBoard; private String jndiName; private Context globalContext; public JNDIDependencyItem(SwitchBoardImpl switchBoard, String jndiName, ControllerState whenRequired, ControllerState dependentState) { this(switchBoard, jndiName, whenRequired, dependentState, false); } public JNDIDependencyItem(SwitchBoardImpl switchBoard, String jndiName, ControllerState whenRequired, ControllerState dependentState, boolean resolved) { super(jndiName, jndiName, whenRequired, dependentState); this.switchBoard = switchBoard; this.jndiName = jndiName; this.setResolved(resolved); //this.tryRegisterNamingListener(); } @Override public boolean resolve(Controller controller) { if (this.isResolved()) { return true; } JavaEEComponent javaeeComp = this.switchBoard.getJavaEEComponent(); if (javaeeComp == null) { // mark as unresolved this.setResolved(false); return this.isResolved(); } CurrentComponent.push(javaeeComp); // The call to dependency resolution happens from within MC and the // TCCL (which the naming server uses for returning the proxies in case of // call by value) won't be correct. So set the correct TCCL (== DU CL which can be // picked up from the switchboard) before doing the lookup ClassLoader oldTCCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.switchBoard.getClassLoader()); try { this.getGlobalContext().lookup(jndiName); // mark as resolved this.setResolved(true); logger.debug("Resolved jndi-name dependency: " + this.jndiName + " based on jndi lookup for switchboard: " + this.switchBoard.getId()); } catch (NameNotFoundException nnfe) { // mark as unresolved this.setResolved(false); } catch (NamingException ne) { throw new RuntimeException("Exception during resolving jndi dependency for jndi name: " + this.jndiName + " for JavaEEComponent " + javaeeComp.getName(), ne); } finally { CurrentComponent.pop(); Thread.currentThread().setContextClassLoader(oldTCCL); } // return the resolution status return this.isResolved(); } @Override public void objectAdded(NamingEvent namingEvent) { Binding binding = namingEvent.getNewBinding(); String boundJNDIName = binding.getName(); if (logger.isTraceEnabled()) { logger.trace(this + " received OBJECT_ADDED event for jndi-name: " + boundJNDIName); } if (this.jndiName.equals(boundJNDIName)) { this.setResolved(true); logger.debug("Resolved jndi-name dependency: " + this.jndiName + " based on naming event for switchboard: " + this.switchBoard.getId()); } } @Override public void objectRemoved(NamingEvent namingEvent) { Binding binding = namingEvent.getNewBinding(); String removedJNDIName = binding.getName(); if (logger.isTraceEnabled()) { logger.trace(this + " received OBJECT_REMOVED event for jndi-name: " + removedJNDIName); } if (this.jndiName.equals(removedJNDIName)) { this.setResolved(false); logger.debug("Naming event received, jndi-name dependency: " + this.jndiName + " un-bound for switchboard: " + this.switchBoard.getId()); } } @Override public void objectRenamed(NamingEvent evt) { // TODO Auto-generated method stub } @Override public void namingExceptionThrown(NamingExceptionEvent evt) { logger.error("NamingException thrown while listening for jndi binding events for jndi name: " + this.jndiName, evt.getException()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getSimpleName()); sb.append("[jndi-name:"); sb.append(this.jndiName); sb.append("switchboard id:"); sb.append(this.switchBoard.getId()); sb.append("]"); return sb.toString(); } private Context getGlobalContext() throws NamingException { if (this.globalContext == null) { this.globalContext = new InitialContext(); } return this.globalContext; } private void tryRegisterNamingListener() { try { Context globalCtx = this.getGlobalContext(); Context ctx = (Context) globalCtx.lookup(""); if (ctx instanceof EventContext) { EventContext eventCtx = (EventContext) ctx; eventCtx.addNamingListener(this.jndiName, EventContext.SUBTREE_SCOPE, this); logger.debug("Using naming event based dependency resolver for jndi-name: " + jndiName + " for switchboard: " + this.switchBoard.getId()); } } catch (Throwable t) { // log and ignore if (logger.isTraceEnabled()) { logger.trace("**** Exception stacktrace can be ignored **** Could not register naming listener for jndi-name: " + this.jndiName + " for switchboard: " + this.switchBoard.getId(), t); } } } }